package com.atom.module.coroutine.core

import com.atom.module.coroutine.cancel.suspendCancellableCoroutine
import com.atom.module.coroutine.context.CoroutineName
import com.atom.module.coroutine.dispatcher.DispatcherContext
import com.atom.module.coroutine.dispatcher.Dispatchers
import com.atom.module.coroutine.scope.CoroutineScope
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.*
import kotlin.coroutines.intrinsics.intercepted


typealias OnComplete = () -> Unit

typealias CancellationException = java.util.concurrent.CancellationException

typealias OnCancel = () -> Unit

typealias OnCompleteT<T> = (Result<T>) -> Unit

private val executor = Executors.newScheduledThreadPool(1) { runnable ->
    Thread(runnable, "Scheduler").apply { isDaemon = true }
}

suspend fun delay(time: Long, unit: TimeUnit = TimeUnit.MILLISECONDS) {
    if (time <= 0) {
        return
    }
    suspendCancellableCoroutine<Unit> { continuation ->
        val future = executor.schedule({
            // 延时1000毫秒后执行续接执行 continuation
            continuation.resume(Unit)
        }, time, unit)
        // 返回一个
        continuation.invokeOnCancellation {
            future.cancel(true)
        }
    }
}


private var coroutineIndex = AtomicInteger(0)

fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    block: suspend CoroutineScope.() -> Unit
): Job {
    val newCoroutineContext = newCoroutineContext(context)
    val completion = StandaloneCoroutine(newCoroutineContext)
    // https://blog.csdn.net/catzifeng/article/details/108913942
    // https://github.com/JetBrains/kotlin/blob/master/libraries/stdlib/jvm/src/kotlin/coroutines/intrinsics/IntrinsicsJvm.kt
    block.startCoroutine(completion, completion)
    return completion
}

fun <T> CoroutineScope.async(
    context: CoroutineContext = Dispatchers.Default,
    block: suspend CoroutineScope.() -> T
): Deferred<T> {
    val completion = DeferredCoroutine<T>(newCoroutineContext(context))
    block.startCoroutine(completion, completion)
    return completion
}

fun CoroutineScope.newCoroutineContext(context: CoroutineContext): CoroutineContext {
    val combined = scopeContext + context + CoroutineName("@coroutine#${coroutineIndex.getAndIncrement()}")
    return if (combined !== Dispatchers.Default && combined[ContinuationInterceptor] == null) combined + Dispatchers.Default else combined
}

fun <T> runBlocking(
    context: CoroutineContext = EmptyCoroutineContext, // 一个空的协程上下文，无任何关联
    block: suspend CoroutineScope.() -> T // 代码执行函数
): T {
    // 创建一个 分发器
    val eventQueue = BlockingQueueDispatcher()
    // 协程上线 的 + 操作实际上是一个 包转和链表的插入操作，目前的空协程上下文为返回的是 + 的入参 也就是 DispatcherContext
    val newContext = context + DispatcherContext(eventQueue)
    // 根据上下文 和 分发器 创建一个 协程作用域 ，并手动开启 其中 协程上下文是必须要给的
    val completion = BlockingCoroutine<T>(newContext, eventQueue)
    // 进行代码执行函数 的执行 将作用域作为入参数 执行开始 也是核心
    // 开始
    // createCoroutineUnintercepted会根据平台生成对应的源代码 源代码的位置 https://github.com/JetBrains/kotlin/blob/master/libraries/stdlib/jvm/src/kotlin/coroutines/intrinsics/IntrinsicsJvm.kt
    // 完成的调用
    //  createCoroutineUnintercepted(receiver, completion).intercepted().resume(Unit)
    // 第一步 执行该方法 返回一个 匿名内部类 ContinuationImpl 从BaseContinuationImpl.kt 查找
    //  createCoroutineUnintercepted(receiver, completion)
    // 第二步 执行并返回一个intercepted 初次返回的是  ContinuationImpl 自己
    //  .intercepted()
    // 第三步执行 执行如下 实际上执行的是
    //  .resume(Unit)  == 执行 ContinuationImpl.resumeWith(Result.success(value)) == 执行 从BaseContinuationImpl.resumeWith(Result.success(value))
    block.startCoroutine(completion, completion)
    // 进行队列的出队操作，由于之前的分发器是基于队列的 所以这里一直进行出队操作，知道队列为空， 这也就是为什么runBlocking会阻塞线程了
    return completion.joinBlocking()
}




